package notify

import (
	"encoding/json"
	"enotify/pkg/notify/conf"
	"enotify/pkg/notify/provider/chuanglan"
	"enotify/pkg/notify/provider/yimei"
	"enotify/pkg/notify/provider/zhixin"
	"errors"
	"fmt"
)
type SmsIDao interface {
	Id() (int64,error)
}
type SMSSender struct {
	c *conf.Config
	d SmsIDao
}

func NewSMSSender(c *conf.Config,d SmsIDao) *SMSSender {
	return &SMSSender{
		c:   c,
		d:   d,
	}
}
func SenderWithSMS(c *conf.Config,d SmsIDao) option{
	return func(s *Sender) {
		s.smsSender = NewSMSSender(c, d)
	}
}
func (s *Sender) SendSms(bizType string,msg SmsMsg) *SendReply{
	reply := NewSendReply(0,"")
	data, err := msg.encode()
	if err != nil  {
		reply.Code = 10001
		reply.Msg = err.Error()
		return reply
	}
	task := Task{
		bizType: bizType,
		data:    data,
		sender:  s.smsSender,
	}
	return s.send(task)
}
func NewSmsMsg(mobiles,msg string,sign string) SmsMsg{
	return SmsMsg{
		Mobiles: mobiles,
		Msg:     msg,
		Sign: sign,
	}
}
type SmsMsg struct {
	Mobiles string `json:"mobiles"`
	Msg string `json:"msg"`
	Sign string `json:"sign"`
}
func(s SmsMsg) encode()([]byte,error){
	data, err := json.Marshal(s)
	return data,err
}
func decodeSMS(data []byte) (SmsMsg,error) {
	var sms SmsMsg
	err := json.Unmarshal(data,&sms)
	return sms,err
}



func (s *SMSSender) Send(bizType string,jn []byte) (reply *SendReply){
	reply = NewSendReply(0,"")
	var err error
	smsMsg,err := decodeSMS(jn)
	if err != nil {
		reply.Code = 10001
		reply.Msg = err.Error()
	}
	var smsConf *conf.SmsConf
	var ok bool
	if smsConf,ok = s.c.Sms[bizType]; ok {
	} else {
		reply.Code = 10001
		reply.Msg = fmt.Sprintf("bizType:%s err",bizType)
		return
	}
	if err != nil {
		reply.Code = 10002
		reply.Msg = err.Error()
	}
	id, _ := s.d.Id()
	switch bizType {
	case "zhixin":
		err = s.sendZhiXin(*smsConf,id,smsMsg)
	case "yimei":
		err = s.sendYiMei(*smsConf, string(id),smsMsg)
	case "chuanglan":
		err = s.sendChuanglan(*smsConf,id,smsMsg)
	}
	ok = errors.As(err, &reply)
	if err != nil && ok {
		reply.Code = 10001
		reply.Msg = err.Error()
		return
	}
	return
}
func (s *SMSSender) sendZhiXin(conf conf.SmsConf, orderId int64,waitMsg SmsMsg) (error){
	zxConf := zhixin.Config{
		ApiKey:    conf.KV["apiKey"],
		CustomId: conf.KV["customId"],
		Version:  conf.KV["version"],
	}
	zx := zhixin.NewZhiXin(zxConf)
	msg :=zhixin.NewMsg(orderId,waitMsg.Sign,waitMsg.Msg,waitMsg.Mobiles)
	reply := NewSendReply(0,"")
	msgId,err := zx.Send(msg)
	if err != nil {
		reply.Code = 10001
		reply.Msg = err.Error()
		return reply
	}
	reply.Reply = msgId
	return reply
	//type zhixinMsg struct {
	//	MerchantOrderId int64 `json:"merchantOrderId"`
	//	Sign string `json:"sign"`
	//	Content string `json:"content"`
	//	Mobiles string `json:"mobiles"`
	//}
	//msg := zhixinMsg{
	//	MerchantOrderId: orderId,
	//	Sign:            waitMsg.Sign,
	//	Content:         waitMsg.Msg,
	//	Mobiles:         waitMsg.Mobiles,
	//}
	//reply := NewSendReply(0,"")
	//data,err := json.Marshal(msg)
	//if err != nil {
	//	reply.Code = 1000
	//	reply.Msg = err.Error()
	//	return reply
	//}
	//sha1Str := fmt.Sprintf("%s%s",string(data),conf.KV["apiKey"])
	//t := sha1.New();
	//io.WriteString(t,sha1Str);
	//sha1Result := fmt.Sprintf("%x",t.Sum(nil))
	//fmt.Println("zhixin------",string(data))
	//fmt.Println("ZHIXIN--------",sha1Result)
	//client := http.Client{
	//	Timeout: time.Second * 3,
	//}
	//headers := map[string]string{
	//	"Content-Type": "application/json; charset=utf-8",
	//	"merchantId":conf.KV["customId"],
	//	"merchantVersion":conf.KV["version"],
	//	"sign":sha1Result,
	//	"Accept":"application/json",
	//}
	//req,err := http.NewRequest("POST","BB",strings.NewReader(string(data)))
	//if err != nil {
	//	reply.Code = 1000
	//	reply.Msg = err.Error()
	//	return reply
	//}
	//for key, header := range headers {
	//	req.Header.Set(key, header)
	//}
	//resp, err := client.Do(req)
	//if err != nil {
	//	reply.Code = 1000
	//	reply.Msg = err.Error()
	//	return reply
	//}
	//defer resp.Body.Close()
	//body, err := ioutil.ReadAll(resp.Body)
	//if err != nil {
	//	reply.Code = 1000
	//	reply.Msg = err.Error()
	//	return reply
	//}
	//type Result struct {
	//	Status string `json:"status"`
	//	Code string `json:"code"`
	//	Msg string `json:"msg"`
	//}
	//fmt.Println("body-------------",string(body))
	//var result Result
	//err = json.Unmarshal(body,&result)
	//if err != nil {
	//	reply.Code = 1000
	//	reply.Msg = err.Error()
	//	return reply
	//}
	//if result.Status == "1" || result.Code == "B000000" {
	//	return nil
	//}
	//reply.Code = 10001
	//reply.Msg = fmt.Sprintf("%s|%s",result.Code,result.Msg)
	//return reply
}
func (s *SMSSender) sendYiMei(conf conf.SmsConf,orderId string,waitMsg SmsMsg) error{
	reply := NewSendReply(0,"")
	ym := yimei.NewYiMei(conf.KV["appId"],conf.KV["passwd"])
	msgId, err := ym.Send(orderId,waitMsg.Mobiles,waitMsg.Msg)
	if err != nil {
		reply.Code = 10001
		reply.Msg = err.Error()
		return reply
	}
	reply.Reply = msgId
	return reply
}
func (s *SMSSender) sendChuanglan(conf conf.SmsConf,orderId int64,waitMsg SmsMsg) error{
	reply := NewSendReply(0,"")
	config := chuanglan.Config{
		Account: conf.KV["account"],
		Passwd:  conf.KV["passwd"],
	}
	msg := chuanglan.NewMsg(orderId,waitMsg.Sign,waitMsg.Msg,waitMsg.Mobiles)
	cl := chuanglan.NewChuangLan(config)
	msgId,err := cl.Send(msg)
	if err != nil {
		reply.Code = 10001
		reply.Msg = err.Error()
		return reply
	}
	reply.Reply = msgId
	return reply
}
